package cn.mw.cmdb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.enums.ModelViewTypeEnum;
import cn.mw.cmdb.enums.OperatorTypeDescEnum;
import cn.mw.cmdb.exception.*;
import cn.mw.cmdb.mongoMapper.InstanceInfoMapper;
import cn.mw.cmdb.mongoMapper.ModelInfoMapper;
import cn.mw.cmdb.param.*;
import cn.mw.cmdb.processor.ModelViewTypeContext;
import cn.mw.cmdb.processor.ModelViewTypeFactory;
import cn.mw.cmdb.processor.ModelViewTypeProccessor;
import cn.mw.cmdb.processor.TableProcessorCommonInstance;
import cn.mw.cmdb.service.ModelManage;
import cn.mw.cmdb.service.TableViewManageService;
import cn.mw.cmdb.util.CMDBTableTool;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.view.ParentModelSelView;
import cn.mw.cmdb.view.TreeViewObject;
import cn.mw.cmdb.view.ViewManager;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.components.mongodb.page.MWIPage;
import cn.mw.components.mongodb.page.MWPage;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.log.client.LogClientSimple;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.api.cmdb.TableIdEnum;
import cn.mw.microMonitorCommon.api.cmdb.TreeView;
import cn.mw.microMonitorCommon.constant.Constants;
import cn.mw.microMonitorCommon.entity.cmdb.TableHeaderItem;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.ModelInfo.PropertyMap;
import static cn.mw.cmdb.entity.ModelType.Normal;
import static cn.mw.cmdb.enums.PageDescEnum.ModelMange;
import static cn.mw.cmdb.util.CMDBTool.initUpdateInfo;

@Slf4j
public class CustomModelServiceImpl extends ModelBaseServiceImpl<ModelInfo, Object> {

    private ModelInfoMapper custModelMapper;

    private InstanceInfoMapper instanceInfoMapper;

    private ModelManage modelManage;

    private CmdbServiceManage cmdbServiceManage;

    private ViewManager viewManager;

    private TableHeaderAndDataManage tableHeaderAndDataManage;

    private TableViewManageService tableViewManageService;
    private LogClientSimple logClientSimple;

    public CustomModelServiceImpl(ModelInfoMapper custModelMapper
            , ModelManage modelManage, InstanceInfoMapper instanceInfoMapper, CmdbServiceManage cmdbServiceManage
            , ViewManager viewManager, TableHeaderAndDataManage tableHeaderAndDataManage, TableViewManageService tableViewManageService
    ) {
        this.modelManage = modelManage;
        this.custModelMapper = custModelMapper;
        this.instanceInfoMapper = instanceInfoMapper;
        this.cmdbServiceManage = cmdbServiceManage;
        this.viewManager = viewManager;
        this.tableHeaderAndDataManage = tableHeaderAndDataManage;
        this.tableViewManageService = tableViewManageService;
        this.logClientSimple = SpringUtil.getBean(LogClientSimple.class);
    }

    public CustomModelServiceImpl() {
        this.logClientSimple = SpringUtil.getBean(LogClientSimple.class);
    }

    public static final String ID = "custom";

    @Override
    Object doAdd(ModelInfo param) throws Exception {
        //获取父模型信息,并把父模型的上一级模型记录到当前模型的继承字段
        List<String> parentIds = param.getParentModelIds();
        if (null != parentIds && parentIds.size() > 0) {
            List<ModelInfo> parentModelInfos = findByIds(parentIds);
            List<String> inheritIds = new ArrayList<>();
            if (null != parentModelInfos) {
                for (ModelInfo pModelInfo : parentModelInfos) {
                    if (null != pModelInfo.getParentModelIds()) {
                        inheritIds.addAll(pModelInfo.getParentModelIds());
                    }

                    if (null != pModelInfo.getInheritModelIds()) {
                        inheritIds.addAll(pModelInfo.getInheritModelIds());
                    }
                }
                if (inheritIds.size() > 0) {
                    param.setInheritModelIds(inheritIds);
                }
            }
        }
        createModelViewField(param);
        CMDBTool.initCreateInfo(param);
        modelCheck(param);
        return custModelMapper.insert(param);
    }

    @Override
    boolean doUpdate(ModelInfo param) throws Exception {
        //检查模型下的实例是否存在, 如果存在则不允许修改
//        long count = countInstanceByModel(param);
//        if(count > 0 ){
//            throw new NotUpdateInstanceExistException();
//        }
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getId).is(param.getId()));
        ModelInfo oldModelInfo = custModelMapper.findOne(query);
        initUpdateInfo(param);
        modelCheck(param);
        //模型修改路径，同步修改资产的路径path
        if(oldModelInfo!=null && oldModelInfo.getGroupPath()!=null && !oldModelInfo.getGroupPath().equals(param.getGroupPath())){
            Query queryInstance = new Query(CriteriaWrapper.where(InstanceInfo::getModelId).is(param.getId()));
            Update updateInstance = new Update();
            String modelGroupId = param.getGroupId();
            List<String> groupPath = param.getGroupPath();
            groupPath.add(param.getId());
            updateInstance.set(CMDBTool.getFieldName(InstanceInfo::getGroupId),modelGroupId);
            updateInstance.set(CMDBTool.getFieldName(InstanceInfo::getPath),groupPath);
            instanceInfoMapper.updateMulti(queryInstance,updateInstance);
        }
        //模型视图修改
        if(oldModelInfo!=null && oldModelInfo.getModelViewType()!=null && !oldModelInfo.getModelViewType().equals(param.getModelViewType())){
            updateModelViewField(param);
        }
        Update update = CMDBTool.genMongoModelUpdate(param);
        CMDBTool.updateFirst(custModelMapper, query, update);
        return true;
    }

    @Override
    boolean doRemove(ModelInfo param) throws Exception {
        ModelInfo modelInfo = selectById(param.getId());
        if (modelInfo.getModelScope().equals(ModelScope.buildin)) {
            throw new DeleteBuildInModelException();
        }

        //检查是否有实例
        if (StringUtils.isNotEmpty(param.getId())) {
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            long count = instanceService.countInstanceInfoByModelId(modelInfo.getId());
            if (count > 0) {
                throw new WarnTitleException("instance-exist-model-del-error");
            }

            //删除关联的属性分类
            ModelPropertyServiceImpl modelPropertyService = (ModelPropertyServiceImpl) cmdbServiceManage.getModelService(ModelPropertyServiceImpl.ID);
            ModelPropertyCatolog modelPropertyCatolog = new ModelPropertyCatolog();
            modelPropertyCatolog.setModelId(param.getId());
            modelPropertyService.delModelPropertyCatolog(modelPropertyCatolog);

            CMDBTool.remove(custModelMapper, param.getId(), ModelInfo.class, true);
            return true;
        }
        return false;
    }

    @Override
    Object doBatchAdd(Object params) {
        return false;
    }

    @Override
    boolean doBatchUpdate(Object params) {
        return false;
    }

    @Override
    public ModelInfo doSelectById(Object id) {
        Object sid = id;
        if (id instanceof ModelInfo) {
            sid = ((ModelInfo) id).getId();
        }
        ModelInfo modelInfo = custModelMapper.findById(sid);
        if (null != modelInfo) {
            modelInfo.setModelManage(modelManage);
        }

        return modelInfo;
    }

    /**
     * 设置模型属性分类排序
     *
     * @param param
     * @return
     * @throws Exception
     */
    public boolean settingModelPropertyCatologList(UpdateModelPropertyCatologParam param) throws Exception {
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getId).is(param.getModelId()));
        Update update = new Update();
        update.set(CMDBTool.getFieldName(ModelInfo::getModelPropertyCatologList), param.getModelPropertyCatologList());
        CMDBTool.updateFirst(custModelMapper, query, update);
        return true;
    }


    /**
     * 返回指定字段的模型数据
     *
     * @param modelIds
     * @return
     */
    public List<ModelInfo> getModelInfoByIncludesField(List<String> modelIds, List<String> includeList) throws Exception {
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getId).in(modelIds));
        if (CollectionUtils.isNotEmpty(includeList)) {
            query.fields().include(includeList.toArray(new String[includeList.size()]));
        }
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        List<ModelInfo> modelInfos = custModelMapper.find(query);
        return modelInfos;
    }

    /**
     * 获取所有的金融元父模型
     * @return
     * @throws Exception
     */
    public List<ModelInfo> getFinanceParentModelInfos() throws Exception {
        ModelSearchParam modelSearchParam = new ModelSearchParam();
        modelSearchParam.addSubCondition(CMDBTool.getFieldName(ModelInfo::getFunctionModule), new SubCondition(CriteriaOpsType.in.name(), FunctionModuleEnum.financeReport.getCode()));
        List<ModelInfo> financeParentModelInfos = getAllModelByParentGroup(modelSearchParam);
        return financeParentModelInfos;
    }



    /**
     * 根据desc查询模型信息
     *
     * @param desc
     * @return
     */
    public ModelInfo getModelInfoByDesc(String desc) throws Exception {
        SearchParam searchParam = new SearchParam();
        searchParam.in(CMDBTool.getFieldName(ModelInfo::getSpec), desc);
        Criteria criteria = genCriteria(searchParam);
        Query query = new Query(criteria);
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        ModelInfo modelInfo = custModelMapper.findOne(query);
        return modelInfo;
    }

    public List<ModelInfo> findAllList() throws Exception {
        ModelSearchParam searchParam = new ModelSearchParam();
        Criteria criteria = genCriteria(searchParam);
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, criteria, searchParam);
        return ret;
    }

    /**
     * 获取所有存在属性的模型
     *
     * @return
     * @throws Exception
     */
    public List<ModelInfo> findModelListByExistsProperty() throws Exception {
        List<String> fieldList = Arrays.asList(CMDBTool.getFieldName(ModelInfo::getId), CMDBTool.getFieldName(ModelInfo::getModelName), CMDBTool.getFieldName(ModelInfo::getProperties));
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        if (CollectionUtils.isNotEmpty(fieldList)) {
            query.fields().include(fieldList.toArray(new String[fieldList.size()]));
        }
        query.addCriteria(Criteria.where(PropertyMap).ne(new Document()));
        List<ModelInfo> ret = custModelMapper.find(query);
        return ret;
    }

    public List<ModelInfo> findModelListByGroups(List<String> modelGroupIds) throws Exception {
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getGroupId).in(modelGroupIds));
        List<ModelInfo> ret = custModelMapper.find(query);
        return ret;
    }


    public List<ModelInfo> findByIds(List<String> ids) throws Exception {
        Query query = new Query();
        if (CollectionUtils.isNotEmpty(ids)) {
            query = new Query(CriteriaWrapper.where(ModelInfo::getId).in(ids));
        }
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        List<ModelInfo> modelInfos = custModelMapper.find(query);
        return modelInfos;
    }

    @Override
    public List<ModelInfo> doSelectList(Object param) throws Exception {
        long time1 = System.currentTimeMillis();
        ModelSearchParam searchParam = (ModelSearchParam) param;
        searchParam.convert();
        Criteria criteria = genCriteria(searchParam);
        long time2 = System.currentTimeMillis();
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, criteria, searchParam);
        long time3 = System.currentTimeMillis();
        log.info("doSelectList::genCriteria耗时：" + (time2 - time1) + "ms;selectAuthorizedList耗时:" + (time3 - time2) + "ms");
        return ret;
    }

    public List<ModelInfo> getListNotAuth(Object param) throws Exception {
        long time1 = System.currentTimeMillis();
        ModelSearchParam searchParam = (ModelSearchParam) param;
        searchParam.convert();
        Criteria criteria = genCriteria(searchParam);
        long time2 = System.currentTimeMillis();
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        if (null != criteria) {
            query.addCriteria(criteria);
        }
        List<ModelInfo> ret = custModelMapper.find(query);
        long time3 = System.currentTimeMillis();
        log.info("getListNotAuth::genCriteria耗时：" + (time2 - time1) + "ms;selectAuthorizedList耗时:" + (time3 - time2) + "ms");
        return ret;
    }

    /**
     * 根据模型分组名模型名称确定指定模型Id
     *
     * @param params
     * @return
     * @throws Exception
     */
    public List<ModelInfo> getModelIdByGroupNameAndModelName(List<QueryGroupAndModelInfo> params, Map<String, List<String>> groupNameByIds) throws Exception {

        List<Criteria> criteriaList = new ArrayList<>();
        for (QueryGroupAndModelInfo groupAndModelInfo : params) {
            Criteria criteria = new Criteria();
            String modelGroupName = groupAndModelInfo.getModelGroupName();
            if (groupNameByIds != null && groupNameByIds.containsKey(modelGroupName)) {
                List<Criteria> criteria2List = new ArrayList<>();
                List<String> groupIds = groupNameByIds.get(modelGroupName);
                Criteria criteriaGroup = new Criteria(CMDBTool.getFieldName(ModelInfo::getGroupPath)).in(groupIds);
                Criteria criteriaModel = new Criteria(CMDBTool.getFieldName(ModelInfo::getModelName)).is(groupAndModelInfo.getModelName());
                criteria2List.add(criteriaGroup);
                criteria2List.add(criteriaModel);
                criteria.andOperator(criteria2List);
            }
            criteriaList.add(criteria);
        }
        Query query = new Query(new Criteria().orOperator(criteriaList));
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        List<ModelInfo> ret = custModelMapper.find(query);
        return ret;
    }

    public Map<String, String> getMapByGroupNameAndModelName(List<QueryGroupAndModelInfo> params) throws Exception {
        Set<String> groupNames = new HashSet<>();
        if (CollectionUtils.isNotEmpty(params)) {
            groupNames = params.stream().map(s -> s.getModelGroupName()).collect(Collectors.toSet());
        }
        ModelGroupServiceImpl modelGroupService = (ModelGroupServiceImpl) cmdbServiceManage.getModelService(ModelGroupServiceImpl.ID);
        GroupSearchParam searchParam = new GroupSearchParam();
        searchParam.setGroupNameList(new ArrayList<>(groupNames));
        List<ModelGroupInfo> showModelGroupList = modelGroupService.getShowModelGroupList(searchParam);

        Map<String, List<String>> groupNameByIds = showModelGroupList.stream().collect(Collectors.groupingBy(s -> s.getName(), Collectors.mapping(ModelGroupInfo::getId, Collectors.toList())));

        Map<String, String> groupIdByName = showModelGroupList.stream().collect(Collectors.toMap(s -> s.getId(), s -> s.getName(), (o1, o2) -> o1));
        List<ModelInfo> modelIdByGroupNameAndModelName = getModelIdByGroupNameAndModelName(params, groupNameByIds);
        Map<String, String> map = new HashMap();
        for (ModelInfo modelInfo : modelIdByGroupNameAndModelName) {
            String modelName = modelInfo.getModelName();
            String groupId = modelInfo.getGroupId();
            if (groupIdByName != null && groupIdByName.containsKey(groupId)) {
                String groupName = groupIdByName.get(groupId);
                map.put(groupName + "_" + modelName, modelInfo.getId());
            }
        }
        return map;

    }


    /**
     * 获取普通模型列表
     *
     * @param param
     * @return
     * @throws Exception
     */
    public List<ModelInfo> doSelectNormalModelList(Object param) throws Exception {
        ModelSearchParam searchParam = (ModelSearchParam) param;
        searchParam.setFields(Arrays.asList(CMDBTool.getFieldName(ModelInfo::getId), CMDBTool.getFieldName(ModelInfo::getModelName)));
        //获取普通模型
        Criteria criteria = new Criteria(CMDBTool.getFieldName(ModelInfo::getModelType)).ne(ModelType.Parent.getType());
        searchParam.convert();
        Criteria criteriaParam = genCriteria(searchParam);
        if (criteriaParam != null) {
            criteria.andOperator(criteriaParam);
        }
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, criteria, searchParam);
        return ret;
    }


    /**
     * 获取父模型分组下的所有父模型模型列表
     *
     * @return
     * @throws Exception
     */
    public List<ModelInfo> getAllModelByParentGroup(ModelSearchParam modelSearchParam) throws Exception {
        List<Criteria> criteriaList = new ArrayList<>();
        //获取普通模型
        Criteria normalCriteria = new Criteria(CMDBTool.getFieldName(ModelInfo::getModelType)).is(ModelType.Parent.getType());
        criteriaList.add(normalCriteria);
        modelSearchParam.convert();
        Criteria criteria1 = genCriteria(modelSearchParam);
        if (criteria1 != null) {
            criteriaList.add(criteria1);
        }
        Criteria criteria = new Criteria().andOperator(criteriaList);
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, criteria, modelSearchParam);
        return ret;
    }

    /**
     * 获取指定分组下的所有显示的普通模型列表
     *
     * @return
     * @throws Exception
     */
    public List<ModelInfo> doSelectShowNormalModelByPath(ModelSearchParam modelSearchParam) throws Exception {
        List<Criteria> criteriaList = new ArrayList<>();
        if (modelSearchParam.getCondition()!=null && !modelSearchParam.getCondition().containsKey(CMDBTool.getFieldName(ModelInfo::getModelType))) {
            // 未指定模型类型时获取普通模型
            Criteria normalCriteria = new Criteria(CMDBTool.getFieldName(ModelInfo::getModelType)).is(Normal.getType());
            criteriaList.add(normalCriteria);
        }
        //获取视图显示的模型
        Criteria showCriteria = new Criteria(CMDBTool.getFieldName(ModelInfo::getDisplay)).is(true);
        criteriaList.add(showCriteria);
        modelSearchParam.convert();
        Criteria criteria1 = genCriteria(modelSearchParam);
        if (criteria1 != null) {
            criteriaList.add(criteria1);
        }
        Criteria criteria = new Criteria().andOperator(criteriaList);
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, criteria, modelSearchParam);
        return ret;
    }

    public List<ModelInfo> selectByGroupId(Long groupId) throws Exception {
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getGroupId).is(groupId));
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        List<ModelInfo> list = custModelMapper.find(query);
        return list;
    }

    public List<ModelInfo> selectByTreeViewList(List<TreeViewObject> treeViewObjectList) throws Exception {
        if (CollectionUtils.isEmpty(treeViewObjectList)) {
            return new ArrayList<>();
        }
        List<String> groupIdList = treeViewObjectList.stream().filter(item -> StringUtils.equals(TableIdEnum.group.getCode(), item.getType())).map(TreeViewObject::getId).toList();
        List<String> modelIdList = treeViewObjectList.stream().filter(item -> StringUtils.equals(TableIdEnum.model.getCode(), item.getType())).map(TreeViewObject::getId).toList();
        List<Criteria> criteriaList = new ArrayList<>();
        Criteria criteria = CriteriaWrapper.where(ModelInfo::getDelFlag).is(false)
                .orOperator(CriteriaWrapper.where(ModelInfo::getGroupId).in(groupIdList), CriteriaWrapper.where(ModelInfo::getId).in(modelIdList));
        criteriaList.add(criteria);
        criteriaList.add(CriteriaWrapper.where(ModelInfo::getDisplay).is(true)
                .andOperator(CriteriaWrapper.where(ModelInfo::getModelType).is(Normal.getType())));
        ModelSearchParam searchParam = new ModelSearchParam();
        searchParam.convert();
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, new Criteria().andOperator(criteriaList), searchParam);
        if (CollectionUtils.isNotEmpty(ret)) {
            ret.forEach(item -> item.setModelManage(modelManage));
        }
        return ret;
    }

    public List<ModelInfo> selectByGroupPathIdsOrModelIds(List<String> groupPathIdList, List<String> modelIdList) throws Exception {
        if (CollectionUtils.isEmpty(groupPathIdList) && CollectionUtils.isEmpty(modelIdList)) {
            return new ArrayList<>();
        }
        List<Criteria> criteriaList = new ArrayList<>();
        Criteria criteria;
        if (CollectionUtils.isNotEmpty(groupPathIdList) && CollectionUtils.isNotEmpty(modelIdList)) {
            criteria = CriteriaWrapper.where(ModelInfo::getDelFlag).is(false)
                    .orOperator(CriteriaWrapper.where(ModelInfo::getGroupPath).in(groupPathIdList), CriteriaWrapper.where(ModelInfo::getId).in(modelIdList));
        } else if (CollectionUtils.isNotEmpty(groupPathIdList)) {
            criteria = CriteriaWrapper.where(ModelInfo::getDelFlag).is(false)
                    .andOperator(CriteriaWrapper.where(ModelInfo::getGroupPath).in(groupPathIdList));
        } else {
            criteria = CriteriaWrapper.where(ModelInfo::getDelFlag).is(false)
                    .andOperator(CriteriaWrapper.where(ModelInfo::getId).in(modelIdList));
        }
        criteriaList.add(criteria);
        criteriaList.add(CriteriaWrapper.where(ModelInfo::getDisplay).is(true)
                .andOperator(CriteriaWrapper.where(ModelInfo::getModelType).is(Normal.getType())));
        ModelSearchParam searchParam = new ModelSearchParam();
        searchParam.convert();
        List<ModelInfo> ret = CMDBTool.selectAuthorizedList(ModelInfo.class, custModelMapper, new Criteria().andOperator(criteriaList), searchParam);
        if (CollectionUtils.isNotEmpty(ret)) {
            ret.forEach(item -> item.setModelManage(modelManage));
        }
        return ret;
    }

    @Override
    boolean doBatchRemove(Object params) {
        return false;
    }

    @Override
    public ModelInfo genObject() {
        return new ModelInfo();
    }

    private long countInstanceByModel(ModelInfo modelInfo) {
        String key = CMDBTool.getFieldName(InstanceInfo::getModelId);
        Query query = new Query(Criteria.where(key).is(modelInfo.getId()));
        long count = instanceInfoMapper.count(query);
        return count;
    }

    public List<ParentModelSelView> findModelsForParentType() throws Exception {
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getModelType).is(ModelType.Parent.getType()));
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        List<ModelInfo> modelInfos = custModelMapper.find(query);
        List<ParentModelSelView> views = new ArrayList<>();
        if (null != modelInfos) {
            for (ModelInfo modelInfo : modelInfos) {
                ParentModelSelView view = new ParentModelSelView(modelInfo.getId(), modelInfo.getModelName());
                views.add(view);
            }
        }

        return views;
    }

    public DataScopeView listScopeData(ListScopeParam param) throws Exception {
        DataScopeView dataScopeView = null;
        switch (param.getTableId()) {
            case group -> dataScopeView = doFindGroupInfo(param);
            case model -> dataScopeView = doFindModelInfo(param);
            case instance -> dataScopeView = doFindInstanceInfo(param);
        }
        return dataScopeView;
    }

    private DataScopeView doFindGroupInfo(ListScopeParam param) throws Exception {
        DataScopeView dataScopeView = new DataScopeView();
        ModelGroupServiceImpl modelGroupService = (ModelGroupServiceImpl) cmdbServiceManage.getModelService(ModelGroupServiceImpl.ID);
        GroupSearchParam groupSearchParam = new GroupSearchParam();
        BeanUtil.copyProperties(param, groupSearchParam);
        List<ModelGroupInfo> modelGroupInfos = modelGroupService.getShowModelGroupList(groupSearchParam);
        if (null != modelGroupInfos) {
            List<String> headItems = new ArrayList<>();
            headItems.add(CMDBTool.getFieldName(ModelGroupInfo::getId));
            headItems.add(CMDBTool.getFieldName(ModelGroupInfo::getName));

            Map<String, String> aliasMap = new HashMap<>();
            aliasMap.put(CMDBTool.getFieldName(ModelGroupInfo::getName), CMDBTool.getFieldName(TreeView::getItemName));

            List<TableHeaderItem> tableHeaderItems = CMDBTableTool.getTableHeaderFromSchema(headItems, aliasMap, ModelGroupInfo.class);
            Set<String> excludeFields = new HashSet<>();
            excludeFields.add(CMDBTool.getFieldName(InstanceInfo::getId));
            List<Map> formatedHeaders = CMDBTableTool.formateTreeTableHeaderV1(tableHeaderItems, excludeFields);
            dataScopeView.setHeader(formatedHeaders);

            List<TreeView> treeViews = new ArrayList<>();
            for (ModelGroupInfo modelGroupInfo : modelGroupInfos) {
                treeViews.add(modelGroupInfo);
            }

            Object ret = CMDBTableTool.formateTreeTableDetailV1(treeViews);
            dataScopeView.setDetails(ret);
            return dataScopeView;
        }

        return null;
    }

    private DataScopeView doFindModelInfo(ListScopeParam param) throws Exception {
        DataScopeView dataScopeView = new DataScopeView();
        ModelSearchParam searchParam = new ModelSearchParam();
        BeanUtil.copyProperties(param, searchParam);
        if (null == searchParam.getPage()) {
            searchParam.setPage(new MWPage());
        }

        List<String> headItems = new ArrayList<>();
        searchParam.setFields(headItems);
        headItems.add(CMDBTool.getFieldName(ModelInfo::getId));
        headItems.add(CMDBTool.getFieldName(ModelInfo::getModelName));
        List<ModelInfo> modelInfos = doSelectNormalModelList(searchParam);
        if (null != modelInfos) {
            List<TableHeaderItem> tableHeaderItems = CMDBTableTool.getTableHeaderFromSchema(headItems, null, ModelInfo.class);
            Set<String> excludeFields = new HashSet<>();
            excludeFields.add(CMDBTool.getFieldName(InstanceInfo::getId));
            List<Map> formatedHeaders = CMDBTableTool.formateTreeTableHeaderV1(tableHeaderItems, excludeFields);
            dataScopeView.setHeader(formatedHeaders);
            MWIPage mwiPage = searchParam.getPage();
            mwiPage.setRecords(modelInfos);
            dataScopeView.setDetails(mwiPage);
        }
        return dataScopeView;
    }

    private DataScopeView doFindInstanceInfo(ListScopeParam param) throws Exception {
        DataScopeView dataScopeView = new DataScopeView();

        TableSearchParam tableSearchParam = new TableSearchParam();
        BeanUtil.copyProperties(param, tableSearchParam);
        if (null == tableSearchParam.getPage()) {
            tableSearchParam.setPage(new MWPage());
        }

        tableSearchParam.setTableId(TableIdEnum.assetType.getCode());
        List<TableHeaderItem> tableHeaderItems = tableHeaderAndDataManage.listHeaders(tableSearchParam);

        Set<String> excludeFields = new HashSet<>();
        excludeFields.add(CMDBTool.getFieldName(InstanceInfo::getId));
        excludeFields.add(TableProcessorCommonInstance.SEQ);
        List<Map> formatedHeaders = CMDBTableTool.formateTableHeaderV1(tableHeaderItems, excludeFields);
        dataScopeView.setHeader(formatedHeaders);

        Object details = tableViewManageService.parseViewData(tableSearchParam);
        dataScopeView.setDetails(details);

        return dataScopeView;
    }

    private void modelCheck(ModelInfo param) throws Exception {
        //同分组下模型名称校验
        Query queryCheck = new Query(CriteriaWrapper.where(ModelInfo::getModelName).is(param.getModelName()));
        queryCheck.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        queryCheck.addCriteria(CriteriaWrapper.where(ModelInfo::getGroupId).is(param.getGroupId()));
        if (!Strings.isNullOrEmpty(param.getId())) {
            queryCheck.addCriteria(CriteriaWrapper.where(ModelInfo::getId).ne(param.getId()));
        }
        long numCheck = custModelMapper.count(queryCheck);
        if (numCheck > 0) {
            throw new ModelExistException("mw-model-exist-err");
        }
        if (!Strings.isNullOrEmpty(param.getModelCode())) {
            String modelCode = param.getModelCode();
            if (!(modelCode.length() == 8 || modelCode.length() == 6)) {
                throw new ModelCodeFormatErrorException(param.getModelName());
            }
            Query query = new Query(CriteriaWrapper.where(ModelInfo::getModelCode).is(modelCode));
            query.addCriteria(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
            if (!Strings.isNullOrEmpty(param.getId())) {
                query.addCriteria(CriteriaWrapper.where(ModelInfo::getId).ne(param.getId()));
            }
            List<ModelInfo> checkModels = custModelMapper.find(query);
            Set<String> checkModelName = checkModels.stream().map(s -> s.getModelName()).collect(Collectors.toSet());
            if (checkModels.size() > 0) {
                throw new ModelCodeExistsException(String.join(",",checkModelName));
            }
        }
    }

    public void createModelViewField(ModelInfo modelInfo) throws Exception {
        modelViewFieldConvert(modelInfo);
    }

    public void updateModelViewField(ModelInfo modelInfo) throws Exception {
        modelViewFieldConvert(modelInfo);
    }

    public void modelViewFieldConvert(ModelInfo modelInfo) throws Exception {
        ModelViewTypeEnum viewType = modelInfo.getModelViewType();
        ModelViewTypeProccessor build = ModelViewTypeFactory.build(viewType);
        ModelViewTypeContext context = new ModelViewTypeContext();
        context.setParam(modelInfo);
        context.setCmdbServiceManage(cmdbServiceManage);
        build.genModelViewProperty(context);
    }

    /**
     * 新增异常日志记录
     *
     * @param param
     */
    public void addRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof ModelInfo) {
            ModelInfo modelInfo = (ModelInfo) param;
            name = modelInfo.getModelName();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        LogClientSimple logClientSimples = SpringUtil.getBean(LogClientSimple.class);
        logClientSimples.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.add.getCname() + ModelMange.getDesc(),
                        OperatorTypeDescEnum.add.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));
    }

    /**
     * 修改异常日志记录
     *
     * @param param
     */
    public void updateRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof ModelInfo) {
            ModelInfo modelInfo = (ModelInfo) param;
            name = modelInfo.getModelName();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.update.getCname() + ModelMange.getDesc(),
                        OperatorTypeDescEnum.update.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));
    }

    /**
     * 删除异常日志记录
     *
     * @param param
     */
    private void removeRecordMethod(Object param) {
        String name = "";
        if (param != null && param instanceof ModelInfo) {
            ModelInfo modelInfo = (ModelInfo) param;
            name = modelInfo.getModelName();
        }
        String nickName = SecurityUtils.getUser().getNickName();
        MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("mwCmdb-operation-log", new Object[]{nickName, DateUtils.now()
                        , BusinessLogType.CMDB_MANAGE.getCnName(), OperatorTypeDescEnum.remove.getCname() + ModelMange.getDesc(),
                        OperatorTypeDescEnum.remove.getCname() + name, Constants.OperationStatus.FAILED}, LocaleContextHolder.getLocale()));
    }

    /**
     * 批量新增异常日志记录
     *
     * @param param
     */
    private void batchAddRecordMethod(Object param) {

    }

    /**
     * 批量修改异常日志记录
     *
     * @param param
     */
    private void batchUpdateRecordMethod(Object param) {

    }

    /**
     * 批量删除异常日志记录
     *
     * @param param
     */
    private void batchRemoveRecordMethod(Object param) {

    }

    public List<String> getAllModelPathName(String modelId) throws Exception {
        List<String> pathNames = new ArrayList<>();
        List<String> fieldList = Arrays.asList(CMDBTool.getFieldName(ModelInfo::getId), CMDBTool.getFieldName(ModelInfo::getModelName), CMDBTool.getFieldName(ModelInfo::getGroupPath));
        Query query = new Query(CriteriaWrapper.where(ModelInfo::getDelFlag).is(false));
        if (CollectionUtils.isNotEmpty(fieldList)) {
            query.fields().include(fieldList.toArray(new String[fieldList.size()]));
        }
        if(!Strings.isNullOrEmpty(modelId)){
            query.addCriteria(CriteriaWrapper.where(ModelInfo::getId).is(modelId));
        }
        query.addCriteria(CriteriaWrapper.where(ModelInfo::getModelType).is(Normal.getType()));
        List<ModelInfo> modelList = custModelMapper.find(query);
        ModelGroupServiceImpl modelGroupService = (ModelGroupServiceImpl) cmdbServiceManage.getModelService(ModelGroupServiceImpl.ID);
        List<ModelGroupInfo> groupInfos = modelGroupService.doSelectAll();
        Map<String, String> groupNameMap = groupInfos.stream().filter(s -> s.getName() != null).collect(Collectors.toMap(s -> s.getId(), s -> s.getName()));
        if(CollectionUtils.isNotEmpty(modelList)){
            for(ModelInfo modelInfo : modelList){
                String pathNameStr = "";
                List<String> groupPath = modelInfo.getGroupPath();
                if(CollectionUtils.isNotEmpty(modelList)){
                    for(String groupId : groupPath){
                        if(groupNameMap!=null && groupNameMap.containsKey(groupId)){
                            String groupName = groupNameMap.get(groupId);
                            pathNameStr += groupName+"/";
                        }
                    }
                    pathNameStr += modelInfo.getModelName();
                    pathNames.add(pathNameStr);
                }
            }
        }
        return pathNames;
    }
}
